use std::path::PathBuf;

use tokio::sync::RwLockWriteGuard;

use crate::test::{
    run_spec_test_with_path,
    spec::{
        unified_runner::{ExpectedCmapEvent, ExpectedEvent, TestFile},
        ExpectedEventType,
    },
    LOCK,
};

use super::run_unified_format_test_filtered;

#[cfg_attr(feature = "tokio-runtime", tokio::test(flavor = "multi_thread"))]
#[cfg_attr(feature = "async-std-runtime", async_std::test)]
async fn run() {
    async fn run_test(path: PathBuf, mut test_file: TestFile) {
        // The Rust driver doesn't support wait queue timeouts.
        if path.ends_with("wait-queue-timeouts.json") {
            return;
        }
        // The Rust driver's asynchronous check-in of connections means that sometimes a new
        // connection will be created, rather than re-using an existing one; the connectionReady
        // events generated by this cause tests to fail, but does not break user-visible behavior.
        // TODO RUST-1055 Remove this workaround.
        for test in &mut test_file.tests {
            if let Some(e) = test.expect_events.as_mut() {
                for expect_events in e {
                    if expect_events.event_type == Some(ExpectedEventType::Cmap) {
                        expect_events.event_type =
                            Some(ExpectedEventType::CmapWithoutConnectionReady);
                        expect_events.events.retain(|ev| {
                            !matches!(
                                ev,
                                ExpectedEvent::Cmap(ExpectedCmapEvent::ConnectionReady {})
                            )
                        });
                    }
                }
            }
        }
        run_unified_format_test_filtered(test_file, |tc| {
            // TODO RUST-142 unskip this when change streams are implemented.
            if tc.description == "change streams pin to a connection" {
                return false;
            }
            true
        })
        .await;
    }
    let _guard: RwLockWriteGuard<()> = LOCK.run_exclusively().await;
    run_spec_test_with_path(&["load-balancers"], run_test).await;
}
